package com.threeox.commonlibrary.util.request;

import android.database.sqlite.SQLiteDatabase;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.threeox.commonlibrary.entity.engine.request.sqlite.OperationTypeMsg;
import com.threeox.commonlibrary.entity.engine.request.sqlite.SqliteRequestMsg;
import com.threeox.commonlibrary.util.RegexHelper;
import com.threeox.commonlibrary.util.sql.TableSqlExecutor;
import com.threeox.ormlibrary.impl.SqlExecutor;
import com.threeox.utillibrary.util.EmptyUtils;
import com.threeox.utillibrary.util.LogUtils;

import java.io.Serializable;
import java.util.List;

/**
 *
 * @ClassName: SqlIteRequestHelper
 *
 * @Description: Todo(本地SqlIte的请求帮助类)
 *
 * @author 赵屈犇
 *
 * @date 创建时间:2017/8/6 下午11:08
 * 
 * @version 1.0
 */
public class SqlIteRequestHelper {

    private final String TAG = "SqlIteRequestHelper";

    private SqlExecutor mSqlExecutor = null;
    private TableSqlExecutor mTableSqlExecutor = null;

    private RequestHelper mRequestHelper;

    private SqlIteRequestHelper(){}

    private SqlIteRequestHelper(RequestHelper requestHelper){
        this.mRequestHelper = requestHelper;
    }

    public static SqlIteRequestHelper newInstance(RequestHelper requestHelper) {
        return new SqlIteRequestHelper(requestHelper);
    }

    /**
     * 请求SqlIte 本地数据库
     *
     * @param requestMsg
     */
    public void execSqlite(final SqliteRequestMsg requestMsg) {
        if (requestMsg == null)
            return;
        try {
            if (mSqlExecutor == null) {
                mSqlExecutor = SqlExecutor.newInstance();
                if (EmptyUtils.isNotEmpty(requestMsg.getDatabasePath())) {
                    try {
                        mSqlExecutor.setSQLiteDatabase(SQLiteDatabase.openOrCreateDatabase(requestMsg.getDatabasePath(), null));
                    } catch (Exception e) {
                        mSqlExecutor = null;
                        mRequestHelper.sendErrorResult(requestMsg, requestMsg.getKey(), e, "打开数据库失败,或许是数据库文件被加密...");
                        return;
                    }
                }
            }
            OperationTypeMsg operationType = requestMsg.getOperationType();
            String executeSQL = RegexHelper.replace$(requestMsg.getExecuteSQL(), requestMsg.getRequestParam());
            if (OperationTypeMsg.INSERT == operationType) {
                execInsertSql(requestMsg, executeSQL);
            } else if (OperationTypeMsg.UPDATE == operationType) {
                execUpdateSql(requestMsg, executeSQL);
            } else if (OperationTypeMsg.REMOVE == operationType) {
                execRemoveSql(requestMsg, executeSQL);
            } else if (OperationTypeMsg.EXECUTESQL == operationType) {
                executeSql(requestMsg, executeSQL);
            } else {
                execSqliteSelect(requestMsg, executeSQL);
            }
        } catch (Exception e) {
            LogUtils.e(TAG, e.getMessage());
            mRequestHelper.sendErrorResult(requestMsg, requestMsg.getKey(), e, e.getMessage());
        }
    }

    /**
     * 执行新增语句
     *
     * @param requestMsg
     * @param executeSQL
     * @throws Exception
     */
    protected void execInsertSql(SqliteRequestMsg requestMsg, String executeSQL) throws Exception {
        Long save = mSqlExecutor.save(requestMsg.getRequestParam(), requestMsg.getTableName());
        if (save != null) {
            mRequestHelper.sendSuccessResult(requestMsg, requestMsg.getKey(), save);
        } else {
            mRequestHelper.sendErrorResult(requestMsg, requestMsg.getKey(), save, "保存数据失败...");
        }
    }

    /**
     * 执行更新语句
     *
     * @param requestMsg
     * @param executeSQL
     * @throws Exception
     */
    protected void execUpdateSql(SqliteRequestMsg requestMsg, String executeSQL) throws Exception {
        Integer update = mSqlExecutor.update(requestMsg.getTableName(), requestMsg.getRequestParam(), requestMsg.getWhereClause(), requestMsg.getWhereArgs());
        if (update != null && update > 0) {
            mRequestHelper.sendSuccessResult(requestMsg, requestMsg.getKey(), update);
        } else {
            mRequestHelper.sendErrorResult(requestMsg, requestMsg.getKey(), update, "更新数据失败...");
        }
    }

    /**
     * 执行删除语句
     *
     * @param requestMsg
     * @param executeSQL
     * @throws Exception
     */
    private void execRemoveSql(SqliteRequestMsg requestMsg, String executeSQL) throws Exception {
        Integer delete = mSqlExecutor.delete(requestMsg.getTableName(), requestMsg.getWhereClause(), requestMsg.getWhereArgs());
        if (delete != null && delete > 0) {
            mRequestHelper.sendSuccessResult(requestMsg, requestMsg.getKey(), delete);
        } else {
            mRequestHelper.sendErrorResult(requestMsg, requestMsg.getKey(), delete, "删除数据失败...");
        }
    }

    /**
     * 动态执行SQL语句
     *
     * @param requestMsg
     * @param executeSQL
     * @throws Exception
     */
    protected void executeSql(SqliteRequestMsg requestMsg, String executeSQL) throws Exception {
        Exception result = mSqlExecutor.executeSql(executeSQL);
        if (result == null) {
            mRequestHelper.sendSuccessResult(requestMsg, requestMsg.getKey(), result);
        } else {
            mRequestHelper.sendErrorResult(requestMsg, requestMsg.getKey(), result, result.getMessage());
        }
    }


    /**
     * 执行SqlIte查询
     *
     * @param requestMsg
     * @param executeSQL
     */
    protected void execSqliteSelect(SqliteRequestMsg requestMsg, String executeSQL) throws Exception {
        String[] paramValues = getQueryRequestParams(requestMsg);
        Object result = null;
        OperationTypeMsg operationType = requestMsg.getOperationType();
        if (OperationTypeMsg.SELECT == operationType) {
            result = mSqlExecutor.query(executeSQL, requestMsg.getResultClass(), paramValues);
        } else if (OperationTypeMsg.SELECTLIST == operationType || OperationTypeMsg.SELECTTABLE == operationType) {
            StringBuffer queryListSql = new StringBuffer(executeSQL);
            JSONObject requestParam = requestMsg.getRequestParam();
            if (requestParam.containsKey(SqliteRequestMsg.OFFSET) && requestMsg.isLimit()) {// 存在当前第几页就是要做分页操作
                int limit = requestParam.containsKey(SqliteRequestMsg.LIMIT) ? requestParam.getIntValue(SqliteRequestMsg.LIMIT) : 20;
                int offset = ( (int) requestMsg.getRequestParam(SqliteRequestMsg.OFFSET)) * limit;
                queryListSql.append(" LIMIT " + offset + " , " + limit);
            }
            LogUtils.d(TAG, "得到最后Sql:" + queryListSql.toString());
            if (OperationTypeMsg.SELECTTABLE == operationType) {
                if (mTableSqlExecutor == null) {
                    mTableSqlExecutor = TableSqlExecutor.newInstance();
                    if (EmptyUtils.isNotEmpty(requestMsg.getDatabasePath())) {
                        mTableSqlExecutor.setSQLiteDatabase(SQLiteDatabase.openOrCreateDatabase(requestMsg.getDatabasePath(), null));
                    }
                }
                result = mTableSqlExecutor.queryTableResult(queryListSql.toString(), executeSQL, requestMsg.getResultClass(), paramValues);
            } else {
                result = mSqlExecutor.queryList(queryListSql.toString(), requestMsg.getResultClass(), paramValues);
            }
            LogUtils.d(TAG, "得到结果:" + JSON.toJSONString(result));
        }
        mRequestHelper.sendSuccessResult(requestMsg, requestMsg.getKey(), (Serializable) result);
    }

    /**
     * 得到查询时的请求参数
     *
     * @param requestMsg
     * @return
     */
    private String[] getQueryRequestParams(SqliteRequestMsg requestMsg) throws Exception {
        List<String> requestParamName = requestMsg.getRequestParamName();
        if (EmptyUtils.isNotEmpty(requestParamName)) {
            String[] result = new String[requestParamName.size()];
            for (int i = 0; i < requestParamName.size(); i++) {
                String paramName = requestParamName.get(i);
                Object paramValue = requestMsg.getRequestParam(paramName);
                result[i] = String.valueOf(paramValue);
            }
            return result;
        }
        return null;
    }

}
